home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / TimeDate.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  20KB  |  940 lines

  1. /*
  2. **    TimeDate.c
  3. **
  4. **    Phone rate calculation support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. ** :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16. VOID
  17. SetActivePattern(struct List *Pattern)
  18. {
  19.     ObtainSemaphore(&PatternSemaphore);
  20.  
  21.     ActivePattern = Pattern;
  22.  
  23.     ReleaseSemaphore(&PatternSemaphore);
  24. }
  25.  
  26. struct List *
  27. GetActivePattern()
  28. {
  29.     struct List *Pattern;
  30.  
  31.     SafeObtainSemaphoreShared(&PatternSemaphore);
  32.  
  33.     Pattern = ActivePattern;
  34.  
  35.     ReleaseSemaphore(&PatternSemaphore);
  36.  
  37.     return(Pattern);
  38. }
  39.  
  40. VOID
  41. UnlockActivePattern()
  42. {
  43.     ReleaseSemaphore(&PatternSemaphore);
  44. }
  45.  
  46. struct List *
  47. LockActivePattern()
  48. {
  49.     SafeObtainSemaphoreShared(&PatternSemaphore);
  50.  
  51.     return(ActivePattern);
  52. }
  53.  
  54.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  55.      *
  56.      *    Free the memory allocated for a TimeDateNode and
  57.      *    the associated data table.
  58.      */
  59.  
  60. VOID
  61. FreeTimeDateNode(struct TimeDateNode *Node)
  62. {
  63.     if(Node)
  64.     {
  65.         FreeVecPooled(Node->Table);
  66.         FreeVecPooled(Node);
  67.     }
  68. }
  69.  
  70.     /* FreeTimeDateList(struct List *List):
  71.      *
  72.      *    Free a list of TimeDateNodes.
  73.      */
  74.  
  75. VOID
  76. FreeTimeDateList(struct List *List)
  77. {
  78.     if(List)
  79.     {
  80.         struct Node *Node;
  81.  
  82.         while(Node = RemHead(List))
  83.             FreeTimeDateNode((struct TimeDateNode *)Node);
  84.     }
  85. }
  86.  
  87.     /* CopyTimeDateList(struct List *From,struct List *To,BOOL SkipFirst):
  88.      *
  89.      *    Copies the TimeDateNode list from one location into
  90.      *    another.
  91.      */
  92.  
  93. BOOL
  94. CopyTimeDateList(struct List *From,struct List *To,BOOL SkipFirst)
  95. {
  96.     if(!IsListEmpty(From))
  97.     {
  98.         struct TimeDateNode *FromNode,*ToNode;
  99.         struct List OtherList;
  100.  
  101.         NewList(&OtherList);
  102.  
  103.         FromNode = (struct TimeDateNode *)From->lh_Head;
  104.  
  105.         if(SkipFirst)
  106.             FromNode = (struct TimeDateNode *)FromNode->Node.ln_Succ;
  107.  
  108.         for( ; FromNode->Node.ln_Succ ; FromNode = (struct TimeDateNode *)FromNode->Node.ln_Succ)
  109.         {
  110.             if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  111.             {
  112.                 CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  113.  
  114.                 ToNode->Node.ln_Name = ToNode->Buffer;
  115.  
  116.                 if(ToNode->Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode->Table[0].Count,MEMF_ANY))
  117.                 {
  118.                     CopyMem(FromNode->Table,ToNode->Table,sizeof(struct TimeDate) * FromNode->Table[0].Count);
  119.  
  120.                     AddTail(&OtherList,&ToNode->Node);
  121.                 }
  122.                 else
  123.                 {
  124.                     FreeVecPooled(ToNode);
  125.  
  126.                     FreeList(&OtherList);
  127.  
  128.                     return(FALSE);
  129.                 }
  130.             }
  131.             else
  132.             {
  133.                 FreeList(&OtherList);
  134.  
  135.                 return(FALSE);
  136.             }
  137.         }
  138.  
  139.         MoveList(&OtherList,To);
  140.     }
  141.  
  142.     return(TRUE);
  143. }
  144.  
  145.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  146.      *
  147.      *    Adapt the title and comment of a TimeDateNode.
  148.      */
  149.  
  150. VOID
  151. AdaptTimeDateNode(struct TimeDateNode *Node)
  152. {
  153.     STRPTR Comment = Node->Header.Comment[0] ? Node->Header.Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  154.  
  155.     if(Node->Header.Month == -1)
  156.     {
  157.         if(Node->Header.Day == -1)
  158.             strcpy(Node->Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  159.         else
  160.             LimitedSPrintf(sizeof(Node->Buffer),Node->Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  161.     }
  162.     else
  163.         LimitedSPrintf(sizeof(Node->Buffer),Node->Buffer,"%2ld %s » %s",Node->Header.Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node->Header.Month),Comment);
  164. }
  165.  
  166.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  167.      *
  168.      *    Comparison routine required by SortTimeTable().
  169.      */
  170.  
  171. STATIC LONG
  172. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  173. {
  174.     return(((LONG)A->Time) - ((LONG)B->Time));
  175. }
  176.  
  177.     /* SortTimeTable(struct TimeDateNode *Node):
  178.      *
  179.      *    Sort the time table associated with a
  180.      *    TimeDateNode in ascending order.
  181.      */
  182.  
  183. VOID
  184. SortTimeTable(struct TimeDateNode *Node)
  185. {
  186.     qsort(Node->Table,Node->Table[0].Count,sizeof(struct TimeDate),(SORTFUNC)TimeCompare);
  187. }
  188.  
  189.     /* BuildTimeList(struct TimeDateNode *Node):
  190.      *
  191.      *    Build a read-to-display time table list from a TimeDateNode.
  192.      */
  193.  
  194. struct List *
  195. BuildTimeList(struct TimeDateNode *Node)
  196. {
  197.     struct List *List;
  198.  
  199.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node->Table[0].Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  200.     {
  201.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  202.         UBYTE             LocalBuffer[40];
  203.         LONG             i;
  204.  
  205.         NewList(List);
  206.  
  207.         for(i = 0 ; i < Node->Table[0].Count ; i++)
  208.         {
  209.             Time[i].Node.ln_Name    = Time[i].Name;
  210.             Time[i].Time            = Node->Table[i].Time;
  211.  
  212.             FormatTime(LocalBuffer,sizeof(LocalBuffer),Time[i].Time / 6,(Time[i].Time % 6) * 10,-1);
  213.  
  214.             LocalBuffer[19] = 0;
  215.  
  216.             strcpy(Time[i].Name,LocalBuffer);
  217.  
  218.             AddTail(List,(struct Node *)&Time[i]);
  219.         }
  220.     }
  221.  
  222.     return(List);
  223. }
  224.  
  225.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  226.      *
  227.      *    Resize the time table associated with a TimeDateNode.
  228.      */
  229.  
  230. BOOL
  231. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  232. {
  233.     if(Count != Node->Table[0].Count)
  234.     {
  235.         struct TimeDate *Table;
  236.  
  237.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  238.         {
  239.             LONG i;
  240.  
  241.             CopyMem(Node->Table,Table,sizeof(struct TimeDate) * Count);
  242.  
  243.             if(Count > Node->Table[0].Count)
  244.             {
  245.                 for(i = Node->Table[0].Count ; i < Count ; i++)
  246.                 {
  247.                     CopyMem(&Node->Table[0],&Table[i],sizeof(struct TimeDate));
  248.  
  249.                     Table[i].Time = Time;
  250.                 }
  251.             }
  252.  
  253.             for(i = 0 ; i < Count ; i++)
  254.                 Table[i].Count = Count;
  255.  
  256.             FreeVecPooled(Node->Table);
  257.  
  258.             Node->Table = Table;
  259.  
  260.             return(TRUE);
  261.         }
  262.         else
  263.             return(FALSE);
  264.     }
  265.     else
  266.         return(TRUE);
  267. }
  268.  
  269.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  270.      *
  271.      *    Delete a single timetable entry from a TimeDateNode.
  272.      */
  273.  
  274. BOOL
  275. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  276. {
  277.     struct TimeDate    *Table;
  278.     LONG             Count = Node->Table[0].Count - 1;
  279.  
  280.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  281.     {
  282.         LONG i,j;
  283.  
  284.         for(i = j = 0 ; i < Node->Table[0].Count ; i++)
  285.         {
  286.             if(i != Index)
  287.             {
  288.                 CopyMem(&Node->Table[i],&Table[j],sizeof(struct TimeDate));
  289.  
  290.                 Table[j++].Count = Count;
  291.             }
  292.         }
  293.  
  294.         FreeVecPooled(Node->Table);
  295.  
  296.         Node->Table = Table;
  297.  
  298.         return(TRUE);
  299.     }
  300.     else
  301.         return(FALSE);
  302. }
  303.  
  304.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  305.      *
  306.      *    Create a new TimeDateNode including time table entries.
  307.      */
  308.  
  309. struct TimeDateNode *
  310. CreateTimeDateNode(LONG Month,LONG Day,STRPTR Comment,LONG Count)
  311. {
  312.     struct TimeDateNode *Node;
  313.  
  314.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  315.     {
  316.         if(Node->Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  317.         {
  318.             Node->Node.ln_Name = Node->Buffer;
  319.  
  320.             Node->Header.Month    = Month;
  321.             Node->Header.Day    = Day;
  322.  
  323.             Node->Table[0].PayPerUnit[DT_FIRST_UNIT]    = 0;
  324.             Node->Table[0].SecPerUnit[DT_FIRST_UNIT]    = 0;
  325.             Node->Table[0].PayPerUnit[DT_NEXT_UNIT]        = 0;
  326.             Node->Table[0].SecPerUnit[DT_NEXT_UNIT]        = 0;
  327.             Node->Table[0].Time                            = DT_GET_TIME( 0,0);
  328.             Node->Table[0].Count                        = Count;
  329.  
  330.             if(Count > 1)
  331.             {
  332.                 Node->Table[1].PayPerUnit[DT_FIRST_UNIT]    = 0;
  333.                 Node->Table[1].SecPerUnit[DT_FIRST_UNIT]    = 0;
  334.                 Node->Table[1].PayPerUnit[DT_NEXT_UNIT]        = 0;
  335.                 Node->Table[1].SecPerUnit[DT_NEXT_UNIT]        = 0;
  336.                 Node->Table[1].Time                            = DT_GET_TIME(12,0);
  337.                 Node->Table[1].Count                        = Count;
  338.             }
  339.  
  340.             strcpy(Node->Header.Comment,Comment);
  341.  
  342.             AdaptTimeDateNode(Node);
  343.  
  344.             return(Node);
  345.         }
  346.         else
  347.             FreeVecPooled(Node);
  348.     }
  349.  
  350.     return(NULL);
  351. }
  352.  
  353. /****************************************************************************/
  354.  
  355.     /* SelectTime():
  356.      *
  357.      *    Searches for the correct unit/pay conversion values.
  358.      */
  359.  
  360. VOID
  361. SelectTime(struct PhoneEntry *SomeEntry,struct List *List,struct timeval *TimeVal)
  362. {
  363.     struct TimeDateNode    *TimeDateNode;
  364.     struct ClockData     ClockData;
  365.     LONG                 Time;
  366.     BOOL                 FoundOne = FALSE;
  367.     LONG                 i,Last;
  368.  
  369.         /* If we get a specific time of day, use it. */
  370.  
  371.     if(TimeVal)
  372.         Amiga2Date(TimeVal->tv_secs,&ClockData);
  373.     else
  374.     {
  375.         struct timeval Now;
  376.  
  377.             /* Obtain current time and date. */
  378.  
  379.         GetSysTime(&Now);
  380.  
  381.             /* Convert into a more suitable form (note: seconds are
  382.              * required as an input value, ice is extra).
  383.              */
  384.  
  385.         Amiga2Date(Now.tv_secs,&ClockData);
  386.     }
  387.  
  388.         /* Apparently, in the US of A the week starts with Sunday, we'll
  389.          * wrap the week around to let it start with Monday.
  390.          */
  391.  
  392.     if(ClockData.wday)
  393.         ClockData.wday--;
  394.     else
  395.         ClockData.wday = 6;
  396.  
  397.         /* Change the month, too... */
  398.  
  399.     ClockData.month--;
  400.  
  401.     if(List)
  402.     {
  403.         if(IsListEmpty(List))
  404.             List = NULL;
  405.     }
  406.  
  407.         /* If no special list to search is given use the phonebook entry. */
  408.  
  409.     if(!List)
  410.     {
  411.         if(SomeEntry && !SomeEntry->Header->NoRates)
  412.             List = (struct List *)&SomeEntry->TimeDateList;
  413.         else
  414.         {
  415.             PayPerUnit[DT_FIRST_UNIT]    = 0;
  416.             PayPerUnit[DT_NEXT_UNIT]    = 0;
  417.             SecPerUnit[DT_FIRST_UNIT]    = 0;
  418.             SecPerUnit[DT_NEXT_UNIT]    = 0;
  419.  
  420.             return;
  421.         }
  422.     }
  423.  
  424.     if(IsListEmpty(List))
  425.     {
  426.         PayPerUnit[DT_FIRST_UNIT]    = 0;
  427.         PayPerUnit[DT_NEXT_UNIT]    = 0;
  428.         SecPerUnit[DT_FIRST_UNIT]    = 0;
  429.         SecPerUnit[DT_NEXT_UNIT]    = 0;
  430.  
  431.         return;
  432.     }
  433.  
  434.         /* First step: search for current day. */
  435.  
  436.     TimeDateNode = (struct TimeDateNode *)List->lh_Head;
  437.  
  438.         /* Skip first entry. */
  439.  
  440.     TimeDateNode = (struct TimeDateNode *)TimeDateNode->Node.ln_Succ;
  441.  
  442.         /* First step: search for date settings. */
  443.  
  444.     for( ; TimeDateNode->Node.ln_Succ ; TimeDateNode = (struct TimeDateNode *)TimeDateNode->Node.ln_Succ)
  445.     {
  446.             /* Does it match a specific date? */
  447.  
  448.         if(TimeDateNode->Header.Month == ClockData.month && TimeDateNode->Header.Day == ClockData.mday)
  449.         {
  450.             FoundOne = TRUE;
  451.  
  452.             break;
  453.         }
  454.     }
  455.  
  456.         /* Second step: search for week day settings. */
  457.  
  458.     if(!FoundOne)
  459.     {
  460.         TimeDateNode = (struct TimeDateNode *)List->lh_Head;
  461.  
  462.             /* Skip first entry. */
  463.  
  464.         TimeDateNode = (struct TimeDateNode *)TimeDateNode->Node.ln_Succ;
  465.  
  466.         for( ; TimeDateNode->Node.ln_Succ ; TimeDateNode = (struct TimeDateNode *)TimeDateNode->Node.ln_Succ)
  467.         {
  468.                 /* Does it match a specific day? */
  469.  
  470.             if(TimeDateNode->Header.Month == -1 && (TimeDateNode->Header.Day & (1L << ClockData.wday)))
  471.             {
  472.                 FoundOne = TRUE;
  473.  
  474.                 break;
  475.             }
  476.         }
  477.     }
  478.  
  479.         /* Third step: use default settings. */
  480.  
  481.     if(!FoundOne)
  482.         TimeDateNode = (struct TimeDateNode *)List->lh_Head;
  483.  
  484.         /* Convert current time to packed format. */
  485.  
  486.     Time = DT_GET_TIME(ClockData.hour,ClockData.min);
  487.  
  488.         /* Start with a blank. */
  489.  
  490.     Last = -1;
  491.  
  492.         /* Look for fitting time. */
  493.  
  494.     for(i = 0 ; i < TimeDateNode->Table[0].Count ; i++)
  495.     {
  496.             /* The time we are looking for must be >= the
  497.              * current time.
  498.              */
  499.  
  500.         if(TimeDateNode->Table[i].Time > Time)
  501.         {
  502.             if(i == 0)
  503.                 break;
  504.             else
  505.             {
  506.                 Last = i - 1;
  507.                 break;
  508.             }
  509.         }
  510.         else
  511.             continue;
  512.     }
  513.  
  514.         /* If none is found, take the last one in the list.
  515.          * Note that this requires the list to be sorted in
  516.          * ascending order.
  517.          */
  518.  
  519.     if(Last == -1)
  520.         Last = TimeDateNode->Table[0].Count - 1;
  521.  
  522.         /* Fill in the remaining data. */
  523.  
  524.     PayPerUnit[DT_FIRST_UNIT]    = TimeDateNode->Table[Last].PayPerUnit[DT_FIRST_UNIT];
  525.     PayPerUnit[DT_NEXT_UNIT]    = TimeDateNode->Table[Last].PayPerUnit[DT_NEXT_UNIT];
  526.     SecPerUnit[DT_FIRST_UNIT]    = TimeDateNode->Table[Last].SecPerUnit[DT_FIRST_UNIT];
  527.     SecPerUnit[DT_NEXT_UNIT]    = TimeDateNode->Table[Last].SecPerUnit[DT_NEXT_UNIT];
  528. }
  529.  
  530. struct List *
  531. FindTimeDate(struct List *Patterns,STRPTR Number)
  532. {
  533.     struct PatternNode    *Node;
  534.     UBYTE                 Dst[2 * 256 + 2];
  535.  
  536.     if(Kick30)
  537.     {
  538.         for(Node = (struct PatternNode *)Patterns->lh_Head ; Node->Node.ln_Succ ; Node = (struct PatternNode *)Node->Node.ln_Succ)
  539.         {
  540.             if(ParsePatternNoCase(Node->Pattern,Dst,sizeof(Dst)) != -1)
  541.             {
  542.                 if(MatchPatternNoCase(Dst,Number))
  543.                     return((struct List *)&Node->List);
  544.             }
  545.         }
  546.     }
  547.     else
  548.     {
  549.         UBYTE    Src[256];
  550.         STRPTR    Index;
  551.  
  552.         for(Node = (struct PatternNode *)Patterns->lh_Head ; Node->Node.ln_Succ ; Node = (struct PatternNode *)Node->Node.ln_Succ)
  553.         {
  554.             strcpy(Index = Src,Node->Pattern);
  555.  
  556.                 /* Work around a bug in Kickstart 2.04 which involves character classes in
  557.                  * wildcard patterns.
  558.                  */
  559.  
  560.             while(*Index)
  561.             {
  562.                 *Index = ToUpper(*Index);
  563.  
  564.                 Index++;
  565.             }
  566.  
  567.             if(ParsePatternNoCase(Src,Dst,sizeof(Dst)) != -1)
  568.             {
  569.                 if(MatchPatternNoCase(Dst,Number))
  570.                     return((struct List *)&Node->List);
  571.             }
  572.         }
  573.     }
  574.  
  575.     return(NULL);
  576. }
  577.  
  578. VOID
  579. DeletePatternNode(struct PatternNode *Pattern)
  580. {
  581.     if(Pattern)
  582.     {
  583.         struct TimeDateNode    *Node,
  584.                             *NextNode;
  585.  
  586.         for(Node = (struct TimeDateNode *)Pattern->List.mlh_Head ; NextNode = (struct TimeDateNode *)Node->Node.ln_Succ ; Node = NextNode)
  587.             FreeTimeDateNode(Node);
  588.  
  589.         FreeVecPooled(Pattern);
  590.     }
  591. }
  592.  
  593. struct PatternNode *
  594. CreatePatternNode(STRPTR Comment)
  595. {
  596.     struct PatternNode *Node;
  597.  
  598.     if(Node = (struct PatternNode *)AllocVecPooled(sizeof(struct PatternNode),MEMF_ANY | MEMF_CLEAR))
  599.     {
  600.         struct TimeDateNode *TimeDateNode;
  601.  
  602.         Node->Node.ln_Name = Node->Comment;
  603.  
  604.         strcpy(Node->Comment,Comment);
  605.  
  606.         NewList((struct List *)&Node->List);
  607.  
  608.         if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  609.         {
  610.             AddTail((struct List *)&Node->List,&TimeDateNode->Node);
  611.  
  612.             return(Node);
  613.         }
  614.  
  615.         FreeVecPooled(Node);
  616.     }
  617.  
  618.     return(NULL);
  619. }
  620.  
  621. VOID
  622. DeletePatternList(struct List *List)
  623. {
  624.     if(List)
  625.     {
  626.         FreePatternList(List);
  627.  
  628.         FreeVecPooled(List);
  629.     }
  630. }
  631.  
  632. VOID
  633. FreePatternList(struct List *List)
  634. {
  635.     if(List)
  636.     {
  637.         struct PatternNode    *Pattern,
  638.                             *NextPattern;
  639.  
  640.         for(Pattern = (struct PatternNode *)List->lh_Head ; NextPattern = (struct PatternNode *)Pattern->Node.ln_Succ ; Pattern = NextPattern)
  641.             DeletePatternNode(Pattern);
  642.  
  643.         NewList(List);
  644.     }
  645. }
  646.  
  647. VOID
  648. ConvertTimeDate(struct TimeDateOld *Old,struct TimeDate *New)
  649. {
  650.     memset(New,0,sizeof(struct TimeDate));
  651.  
  652.     New->Count            = Old->Count;
  653.     New->PayPerUnit[0]    = ((ULONG)Old->PayPerUnit[0]) * 10000;
  654.     New->PayPerUnit[1]    = ((ULONG)Old->PayPerUnit[1]) * 10000;
  655.     New->SecPerUnit[0]    = ((ULONG)Old->SecPerUnit[0]) * 10000;
  656.     New->SecPerUnit[1]    = ((ULONG)Old->SecPerUnit[1]) * 10000;
  657.     New->Time            = Old->Time;
  658.     New->Mark            = FALSE;
  659. }
  660.  
  661. struct List *
  662. LoadTimeDateList(STRPTR Name,LONG *Error)
  663. {
  664.     struct IFFHandle    *Handle;
  665.     struct List            *List = NULL;
  666.  
  667.     *Error = 0;
  668.  
  669.     if(Handle = OpenIFFStream(Name,MODE_OLDFILE))
  670.     {
  671.         STATIC LONG Stops[4 * 2] =
  672.         {
  673.             ID_TERM, ID_VERS,
  674.             ID_TERM, ID_NAME,
  675.             ID_TERM, ID_DAT2,
  676.             ID_TERM, ID_DATE
  677.         };
  678.  
  679.         struct ContextNode *Chunk;
  680.  
  681.         if(!(*Error = StopChunks(Handle,Stops,4)))
  682.         {
  683.             if(List = CreateList())
  684.             {
  685.                 struct PatternNode *Pattern = NULL;
  686.  
  687.                 while(!ParseIFF(Handle,IFFPARSE_SCAN))
  688.                 {
  689.                     Chunk = CurrentChunk(Handle);
  690.  
  691.                     if(Chunk->cn_ID == ID_NAME)
  692.                     {
  693.                         if(Pattern = (struct PatternNode *)AllocVecPooled(sizeof(struct PatternNode),MEMF_ANY | MEMF_CLEAR))
  694.                         {
  695.                             if(ReadChunkBytes(Handle,Pattern->Pattern,Chunk->cn_Size) == Chunk->cn_Size)
  696.                             {
  697.                                 NewList((struct List *)&Pattern->List);
  698.  
  699.                                 Pattern->Node.ln_Name = Pattern->Comment;
  700.  
  701.                                 AddTail(List,(struct Node *)Pattern);
  702.                             }
  703.                             else
  704.                             {
  705.                                 *Error = IoErr();
  706.  
  707.                                 FreeVecPooled(Pattern);
  708.  
  709.                                 break;
  710.                             }
  711.                         }
  712.                         else
  713.                         {
  714.                             *Error = ERROR_NO_FREE_STORE;
  715.  
  716.                             break;
  717.                         }
  718.                     }
  719.  
  720.                     if(Chunk->cn_ID == ID_DATE)
  721.                     {
  722.                         struct TimeDateNode    *Node;
  723.                         LONG                 Count = (Chunk->cn_Size - sizeof(struct TimeDateHeader)) / sizeof(struct TimeDateOld);
  724.  
  725.                         if(!Pattern)
  726.                         {
  727.                             *Error = IFFERR_MANGLED;
  728.  
  729.                             break;
  730.                         }
  731.  
  732.                         if(Node = CreateTimeDateNode(-1,-1,"",Count))
  733.                         {
  734.                             struct TimeDateOld *Old;
  735.  
  736.                             if(Old = (struct TimeDateOld *)AllocVecPooled(sizeof(struct TimeDateOld) * Count,MEMF_ANY))
  737.                             {
  738.                                 if(ReadChunkBytes(Handle,&Node->Header,sizeof(struct TimeDateHeader)) == sizeof(struct TimeDateHeader))
  739.                                 {
  740.                                     if(ReadChunkRecords(Handle,Old,sizeof(struct TimeDateOld),Count) == Count)
  741.                                     {
  742.                                         LONG i;
  743.  
  744.                                         for(i = 0 ; i < Count ; i++)
  745.                                             ConvertTimeDate(&Old[i],&Node->Table[i]);
  746.  
  747.                                         AdaptTimeDateNode(Node);
  748.  
  749.                                         AddTail((struct List *)&Pattern->List,&Node->Node);
  750.  
  751.                                         FreeVecPooled(Old);
  752.                                     }
  753.                                     else
  754.                                     {
  755.                                         *Error = IoErr();
  756.  
  757.                                         FreeTimeDateNode(Node);
  758.                                         FreeVecPooled(Old);
  759.  
  760.                                         break;
  761.                                     }
  762.                                 }
  763.                                 else
  764.                                 {
  765.                                     *Error = IoErr();
  766.  
  767.                                     FreeTimeDateNode(Node);
  768.                                     FreeVecPooled(Old);
  769.  
  770.                                     break;
  771.                                 }
  772.                             }
  773.                         }
  774.                         else
  775.                         {
  776.                             *Error = ERROR_NO_FREE_STORE;
  777.                             break;
  778.                         }
  779.                     }
  780.  
  781.                     if(Chunk->cn_ID == ID_DAT2)
  782.                     {
  783.                         struct TimeDateNode    *Node;
  784.                         LONG                 Count = (Chunk->cn_Size - sizeof(struct TimeDateHeader)) / sizeof(struct TimeDate);
  785.  
  786.                         if(!Pattern)
  787.                         {
  788.                             *Error = IFFERR_MANGLED;
  789.  
  790.                             break;
  791.                         }
  792.  
  793.                         if(Node = CreateTimeDateNode(-1,-1,"",Count))
  794.                         {
  795.                             if(ReadChunkBytes(Handle,&Node->Header,sizeof(struct TimeDateHeader)) == sizeof(struct TimeDateHeader))
  796.                             {
  797.                                 if(ReadChunkRecords(Handle,Node->Table,sizeof(struct TimeDate),Count) == Count)
  798.                                 {
  799.                                     AdaptTimeDateNode(Node);
  800.  
  801.                                     AddTail((struct List *)&Pattern->List,&Node->Node);
  802.                                 }
  803.                                 else
  804.                                 {
  805.                                     *Error = IoErr();
  806.  
  807.                                     FreeTimeDateNode(Node);
  808.  
  809.                                     break;
  810.                                 }
  811.                             }
  812.                             else
  813.                             {
  814.                                 *Error = IoErr();
  815.  
  816.                                 FreeTimeDateNode(Node);
  817.  
  818.                                 break;
  819.                             }
  820.                         }
  821.                         else
  822.                         {
  823.                             *Error = ERROR_NO_FREE_STORE;
  824.                             break;
  825.                         }
  826.                     }
  827.                 }
  828.             }
  829.         }
  830.  
  831.         CloseIFFStream(Handle);
  832.     }
  833.     else
  834.         *Error = IoErr();
  835.  
  836.     if(*Error)
  837.     {
  838.         DeletePatternList(List);
  839.  
  840.         return(NULL);
  841.     }
  842.     else
  843.         return(List);
  844. }
  845.  
  846. BOOL
  847. SaveTimeDateList(STRPTR Name,struct List *List,LONG *Error)
  848. {
  849.     *Error = 0;
  850.  
  851.     if(!IsListEmpty(List))
  852.     {
  853.         struct IFFHandle *Handle;
  854.  
  855.         if(Handle = OpenIFFStream(Name,MODE_NEWFILE))
  856.         {
  857.             if(!(*Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  858.             {
  859.                 if(!(*Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  860.                 {
  861.                     struct TermInfo TermInfo;
  862.  
  863.                     TermInfo.Version    = CONFIG_FILE_VERSION;
  864.                     TermInfo.Revision    = CONFIG_FILE_REVISION;
  865.  
  866.                     if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1) == 1)
  867.                     {
  868.                         if(!(*Error = PopChunk(Handle)))
  869.                         {
  870.                             struct PatternNode *Node;
  871.  
  872.                             for(Node = (struct PatternNode *)List->lh_Head ; !(*Error) && Node->Node.ln_Succ ; Node = (struct PatternNode *)Node->Node.ln_Succ)
  873.                             {
  874.                                 if(!(*Error = PushChunk(Handle,0,ID_NAME,296)))
  875.                                 {
  876.                                     if(WriteChunkBytes(Handle,Node->Pattern,296) == 296)
  877.                                     {
  878.                                         if(!(*Error = PopChunk(Handle)))
  879.                                         {
  880.                                             struct TimeDateNode *TimeDateNode;
  881.  
  882.                                             for(TimeDateNode = (struct TimeDateNode *)Node->List.mlh_Head ; TimeDateNode->Node.ln_Succ ; TimeDateNode = (struct TimeDateNode *)TimeDateNode->Node.ln_Succ)
  883.                                             {
  884.                                                 if(!(*Error = PushChunk(Handle,0,ID_DAT2,sizeof(struct TimeDateHeader) + TimeDateNode->Table[0].Count * sizeof(struct TimeDate))))
  885.                                                 {
  886.                                                     if(WriteChunkBytes(Handle,&TimeDateNode->Header,sizeof(struct TimeDateHeader)) != sizeof(struct TimeDateHeader))
  887.                                                     {
  888.                                                         *Error = IoErr();
  889.  
  890.                                                         break;
  891.                                                     }
  892.                                                     else
  893.                                                     {
  894.                                                         if(WriteChunkBytes(Handle,TimeDateNode->Table,TimeDateNode->Table[0].Count * sizeof(struct TimeDate)) != TimeDateNode->Table[0].Count * sizeof(struct TimeDate))
  895.                                                         {
  896.                                                             *Error = IoErr();
  897.  
  898.                                                             break;
  899.                                                         }
  900.                                                         else
  901.                                                         {
  902.                                                             if(*Error = PopChunk(Handle))
  903.                                                                 break;
  904.                                                         }
  905.                                                     }
  906.                                                 }
  907.                                                 else
  908.                                                     break;
  909.                                             }
  910.                                         }
  911.                                     }
  912.                                     else
  913.                                         *Error = IoErr();
  914.                                 }
  915.                             }
  916.                         }
  917.                     }
  918.                 }
  919.  
  920.                 if(!(*Error))
  921.                     *Error = PopChunk(Handle);
  922.             }
  923.  
  924.             if(*Error)
  925.                 DeleteFile(Name);
  926.             else
  927.                 AddProtection(Name,FIBF_EXECUTE);
  928.  
  929.             CloseIFFStream(Handle);
  930.         }
  931.         else
  932.             *Error = IoErr();
  933.     }
  934.  
  935.     if(*Error)
  936.         return(FALSE);
  937.     else
  938.         return(TRUE);
  939. }
  940.